#include "LocationFinder.h"

#ifdef HAVE_QTM_LOCATION
#include <QGeoCoordinate>
#include <QPointF>
#include <QSettings>
#include <QTimer>

using QtMobility::QGeoCoordinate;

static const qreal updateThresholdDistance = 0.001;

QGeoPositionInfoSource* LocationFinder::positionSource = 0;

LocationFinder::LocationFinder()
{
    if(!positionSource)
        positionSource = QGeoPositionInfoSource::createDefaultSource(this);

    if(positionSource) {
        connect(positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)),
                this, SLOT(positionUpdated(QGeoPositionInfo)));
    }

    loadLocationFromSettings();
}

LocationFinder::~LocationFinder()
{
    saveLocationToSettings();
}

void LocationFinder::saveLocationToSettings()
{
    QSettings settings;
    settings.setValue("latitude", lastPosition.coordinate().latitude());
    settings.setValue("longitude", lastPosition.coordinate().longitude());
    settings.setValue("formattedAddress", formattedAddress);
    settings.setValue("positionTimestamp", lastPosition.timestamp());
}

void LocationFinder::loadLocationFromSettings()
{
    lastPosition = positionSource->lastKnownPosition();
    formattedAddress = "";

    QSettings settings;
    QVariant time = settings.value("positionTimestamp");
    QDateTime timestamp;
    if (time.isValid() &&
        time.canConvert(QVariant::DateTime) &&
        (timestamp = time.toDateTime()) > lastPosition.timestamp()) {
        qreal latitude = settings.value("latitude").toReal();
        qreal longitude = settings.value("longitude").toReal();
        formattedAddress = settings.value("formattedAddress").toString();
        lastPosition = QGeoPositionInfo(QGeoCoordinate(latitude, longitude), timestamp);
    }
}

const QtMobility::QGeoPositionInfo& LocationFinder::getCurrentPosition() const
{
    return lastPosition;
}

QString LocationFinder::getFormattedAddress() const
{
    return formattedAddress;
}

void LocationFinder::positionUpdated(const QGeoPositionInfo &update)
{
    lastPosition = QGeoPositionInfo(update);

    // workaround to bug http://bugreports.qt.nokia.com/browse/QTMOBILITY-398
    // should be removed after this gets fixed in Qt Mobility
    QDateTime timestamp = update.timestamp();
    timestamp.setTimeSpec(Qt::UTC);
    lastPosition.setTimestamp(timestamp);

    QVector2D p(update.coordinate().latitude(), update.coordinate().longitude());
    // if position is close to last position then we don't reset formatted address
    // since we assume that it has the same address
    if (!isCloseToLastPosition(p))
        formattedAddress = "";

    qDebug("Position updated");

    emit positionUpdated();
}

void LocationFinder::formattedAddressResolved(qreal latitude, qreal longitude, const QString &formattedAddress)
{
    if (isCloseToLastPosition(QVector2D(latitude, longitude))) {
        this->formattedAddress = formattedAddress;
        emit positionUpdated();
    }
}

bool LocationFinder::isCloseToLastPosition(const QVector2D &pos)
{
    QVector2D p(lastPosition.coordinate().latitude(), lastPosition.coordinate().longitude());
    return (p - pos).length() < updateThresholdDistance;
}

void LocationFinder::fakePositionUpdate()
{
    lastPosition = QGeoPositionInfo(QtMobility::QGeoCoordinate(60.05, 20.543), QDateTime::currentDateTime());
    emit positionUpdated();
}

void LocationFinder::reset()
{
    stopSearchingForLocation();
    lastPosition = QGeoPositionInfo();
    formattedAddress = "";
}

void LocationFinder::stopSearchingForLocation()
{
    if(positionSource) {
        positionSource->stopUpdates();
    }
}

void LocationFinder::startSearchingForLocation()
{
   if(positionSource) {
       qDebug("Position source exists, starting search");
       positionSource->startUpdates();
       emit positionUpdated();
   }
   
   //QTimer::singleShot(5000, this, SLOT(fakePositionUpdate()));
}

#endif // HAVE_QTM_LOCATION
